//
//  JuInit.swift
//  JuSwift
//
//  Created by Juvid on 2017/6/30.
//  Copyright © 2017年 Juvid. All rights reserved.
//

import UIKit

//1重写父类的构造器
class Person{
    var name: String
    var color: String
    
    //指定构造器
    init(name: String, color: String){
        self.name = name
        self.color = color
    }
    
    init(){
        self.name = "小明"
        self.color = "小黄人"
    }
    
    //便利构造器
    convenience init(name:String){
        self.init(name: name, color: "黑人")
    }
    
}
//对父类的构造器进行重写
class Man: Person {
    var height: Double
    
    //如果子类方法和父类方法同名，编译器默认它为重写方法
    override init(name: String, color: String) {
        //对自身的属性进行初始化
        height = 1.80
        
        //调用父类的构造方法对从父类继承的属性进行初始化
        super.init(name: name, color: color)
    }
    
    override init() {
        height = 1.75
        super.init(name: "小花", color: "白人")
    }
    
    //子类永远不能直接访问父类中的便利构造器，所以此处定义的构造方法不是重写方法
    init(name: String){
        height = 1.70
        super.init()
        self.color = "yellow"
        self.name = "Lilei"
    }
}

var m = Man(name: "hello", color: "world")

/*
 *2required关键字
 
 1:required关键字，只能用于修饰构造方法
 
 2: 【提问】 继承中required修饰的构造方法是否是必须实现的方法?
 */

class Fruit{
    var name: String
    
    required init(name: String){
        self.name = name
    }
    
    required convenience init(){
        self.init(name: "水果")
    }
}
class Pear: Fruit {
    var weight: Double = 0.0
}
//1.当子类没实现任何构造方法，编译器就会认为子类可以使用父类中的所有指定构造器，required修饰的构造方法在子类中可以不写
var xpear = Pear.init(name: "梨")


//2.当子类中定义了异于父类中的构造方法(参数名称不同、参数个数不同、参数类型不同)，
//那么父类中使用required修饰的构造方法在子类中必须实现，而且这个方法必须使用required关键字而不能使用override修饰
class Apple: Fruit {
    var sweet: String = ""
    
    init(sweet:String){
        self.sweet = sweet
        super.init(name: "apple")
    }
    
    required init(name: String) {
        self.sweet = ""
        super.init(name: name)
    }
}


/**
func lainxi() {
    
    //1.首先定义一个基类，一说到required修饰符，我们最先想到的应该就是普通类（class）的init()方法了
    class MyClass {
        var str:String
        init(str:String) {
            self.str = str
        }
    }
    
    //2.定义一个MyClass 的子类 MySubClass
    class MySubClass:MyClass {
        
    }
    
    let a1 =  MySubClass(str:"Hello Swift")//继承了它父类
    print(a1.str)//Hello swift
    
    class MySubClass2:MyClass {
        
        override init(str:String) {//init()方法前加上override修饰符，表示MySubClass重写了其父类的init()方法，然后还要调用父类的init()方法，并将参数一并传给父类的方法
            super.init(str:str)
        }
    }
    
    let a2 =  MySubClass2(str:"Hello Swift")
    print(a2.str)////Hello Swift
    
    /*应用：
     ** 比如 子类化的时候需要自定义初始化方法
     */
    class MySubClass3:MyClass
    {
        //当子类的初始化方法参数类型与父类的初始化方法参数类型不同时，我们就不必在子类的初始化方法前加override修饰符了
        //但是要把子类初始化方法的参数类型转换为符合父类初始化方法的参数类型，然后传给父类的初始化方法
        init(i:Int) {
            super.init(str:String(i))
        }
    }
    let a3 =  MySubClass3(i: 10)
    
    
    
    //required修饰符
    //给父类的init()方法加上required修饰符
    class SomeClass {
        var str:String
        required init(str:String) {
            self.str = str
        }
    }
    
    //        class SomeSubClass:SomeClass
    //        {
    //            init(i:Int) {
    //                super.init(str:String(i))
    //            }
    //
    //            // 编译错误  上面的代码在编译会发生错误，因为我们没有实现父类中要去必须要实现的方法
    //        }
    
    
    class SomeSubClass:SomeClass {
        required init(str:String) {
            super.init(str: str)
        }
        //            required init(str: String) {
        //                fatalError("init(str:) has not been implemented")
        //            }
        init(i:Int) {
            super.init(str:String(i))
        }
        
    }
    //从上面的代码示例中不难看出，如果子类需要添加异于父类的初始化方法时，必须先要实现父类中使用required修饰符修饰过的初始化方法，并且也要使用required修饰符而不是override。
    //如果子类中不需要添加任何初始化方法，我们则可以忽略父类的required初始化方法：
    
    /*
     **
     required修饰符的使用规则
     required修饰符只能用于修饰类初始化方法。
     当子类含有异于父类的初始化方法时（初始化方法参数类型和数量异于父类），子类必须要实现父类的required初始化方法，并且也要使用required修饰符而不是override。
     当子类没有初始化方法时，可以不用实现父类的required初始化方法。
     */
    
    let a4 = SomeSubClass(i: 10)
    
}

/*
 ** 应用：
 *  比如：在子类化视图的时候 重写初始化方法的时候需要：
 override init(frame: CGRect) {
 super.init(frame: frame)
 
 
 }
 
 required init?(coder aDecoder: NSCoder) {
 fatalError("init(coder:) has not been implemented")
 }
 这也是解释重写初始化方法的时候 不写上面的方法会提示错误的原因
 */


 
 *
 */
